%%%-------------------------------------------------------------------
%%% @author Administrator
%%% @copyright (C) 2023, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 12. 4月 2023 15:11
%%%-------------------------------------------------------------------
-module(sc_element).
-behaviour(gen_server).
-export([
  start_link/2, % (以下6行)导出的API函数
  create/2,
  create/1,
  fetch/1,
  replace/2,
  delete/1
]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
  terminate/2, code_change/3]).
-define(SERVER, ?MODULE).
-define(DEFAULT_LEASE_TIME, (60 * 60 * 24)). % 一天中的总秒数
-record(state, {value, lease_time, start_time}).

start_link(Value, LeaseTime) ->
  gen_server:start_link(?MODULE, [Value, LeaseTime], []).
create(Value, LeaseTime) ->
  sc_element_sup:start_child(Value, LeaseTime). % 将启动委托给sc_sup
create(Value) ->
  create(Value, ?DEFAULT_LEASE_TIME).
fetch(Pid) ->
  gen_server:call(Pid, fetch).
replace(Pid, Value) ->
  gen_server:cast(Pid, {replace, Value}).
delete(Pid) ->
  gen_server:cast(Pid, delete).



init([Value, LeaseTime]) ->
  Now = calendar:local_time(),
  StartTime = calendar:datetime_to_gregorian_seconds(Now),
  {ok,
    #state{value = Value, % 初始化进程状态
      lease_time = LeaseTime,
      start_time = StartTime},
    time_left(StartTime, LeaseTime)}. % 初始化超时设置
time_left(_StartTime, infinity) ->
  infinity;
time_left(StartTime, LeaseTime) ->
  Now = calendar:local_time(),
  CurrentTime = calendar:datetime_to_gregorian_seconds(Now),
  TimeElapsed = CurrentTime - StartTime,
  case LeaseTime - TimeElapsed of
    Time when Time =< 0 -> 0;
    Time -> Time * 1000
  end.
handle_call(fetch, _From, State) ->
  #state{value = Value,
    lease_time = LeaseTime,
    start_time = StartTime} = State,
  TimeLeft = time_left(StartTime, LeaseTime),
  {reply, {ok, Value}, State, TimeLeft}. % ❶ 取出进程状态中的值
handle_cast({replace, Value}, State) ->
  #state{lease_time = LeaseTime,
    start_time = StartTime} = State,
  TimeLeft = time_left(StartTime, LeaseTime),
  {noreply, State#state{value = Value}, TimeLeft};
handle_cast(delete, State) ->
  {stop, normal, State}. % ❷ 发出关闭信号
handle_info(timeout, State) ->
  {stop, normal, State}.
terminate(_Reason, _State) ->
  sc_store:delete(self()), % ❸ 删除进程的键
  ok.
code_change(_OldVsn, State, _Extra) ->
  {ok, State}.
